package io.e2x.testground.fruitstore.repo;

import io.e2x.testground.fruitstore.common.Constants;
import io.e2x.testground.fruitstore.common.error.RetryException;
import io.e2x.testground.fruitstore.dal.entities.Sku;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.concurrent.atomic.AtomicReference;

@Repository
public interface SkuRepo extends ReactiveCrudRepository<Sku, Long> {
    Flux<Sku> findByNameAndStoreId(String name, long storeId);

    Mono<Sku> findByName(String name);

    Mono<Sku> findById(long id);

    default Mono<Void> updateStock(long id, Integer count){
        return findById(id)
                .flatMap(sku -> {
                    if (sku.getStock() < count) {
                        return Mono.error(new RuntimeException("库存不足"));
                    }
                    sku.setStock(sku.getStock() - count);
                    sku.setCount(sku.getCount() + count);
                    return Mono.just(sku);
                })
                .flatMap(this::save)
                .then()
                .onErrorMap(OptimisticLockingFailureException.class, e -> new RetryException("乐观锁超过最大重试次数"))
                .retryWhen(
                        reactor.util.retry.Retry.backoff(Constants.MAX_LOCK_RETRY_TIMES, java.time.Duration.ofMillis(100))
                                .filter(RetryException.class::isInstance)
                );
    }
}
